package cn.turboinfo.fuyang.api.provider.admin.impl.cms;

import cn.turboinfo.fuyang.api.domain.admin.service.cms.CmsCategoryService;
import cn.turboinfo.fuyang.api.entity.admin.exception.cms.CmsCategoryException;
import cn.turboinfo.fuyang.api.entity.admin.pojo.cms.CmsCategory;
import cn.turboinfo.fuyang.api.entity.admin.pojo.cms.CmsCategoryCreator;
import cn.turboinfo.fuyang.api.entity.admin.pojo.cms.CmsCategoryUpdater;
import cn.turboinfo.fuyang.api.provider.admin.repository.database.cms.CmsCategoryDAO;
import cn.turboinfo.fuyang.api.provider.admin.repository.database.cms.CmsCategoryPO;
import net.sunshow.toolkit.core.qbean.api.request.QPage;
import net.sunshow.toolkit.core.qbean.api.request.QRequest;
import net.sunshow.toolkit.core.qbean.api.response.QResponse;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanCreatorHelper;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanUpdaterHelper;
import net.sunshow.toolkit.core.qbean.helper.service.impl.AbstractQServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;

@Service
public class CmsCategoryServiceImpl extends AbstractQServiceImpl<CmsCategory> implements CmsCategoryService {
    private CmsCategoryDAO categoryDAO;

    @Override
    public Optional<CmsCategory> getById(Long id) {
        return categoryDAO.findById(id).map(this::convertQBean);
    }

    @Override
    public CmsCategory getByIdEnsure(Long id) {
        return getById(id).orElseThrow(this.getExceptionSupplier("未找到数据, id=" + id, null));
    }

    @Override
    public List<CmsCategory> findByIdCollection(Collection<Long> idCollection) {
        return convertStreamQBeanToList(categoryDAO.findByIdInOrderByIdDesc(idCollection).stream());
    }

    @Override
    @Transactional
    public CmsCategory save(CmsCategoryCreator creator) throws CmsCategoryException {
        CmsCategoryPO categoryPO = new CmsCategoryPO();

        QBeanCreatorHelper.copyCreatorField(categoryPO, creator);

        return convertQBean(categoryDAO.save(categoryPO));
    }

    @Override
    @Transactional
    public CmsCategory update(CmsCategoryUpdater updater) throws CmsCategoryException {
        CmsCategoryPO categoryPO = getEntityWithNullCheckForUpdate(updater.getUpdateId(), categoryDAO);

        QBeanUpdaterHelper.copyUpdaterField(categoryPO, updater);

        return convertQBean(categoryPO);
    }

    @Override
    public QResponse<CmsCategory> findAll(QRequest request, QPage requestPage) {
        return convertQResponse(findAllInternal(request, requestPage));
    }

    private Page<CmsCategoryPO> findAllInternal(QRequest request, QPage requestPage) {
        return categoryDAO.findAll(convertSpecification(request), convertPageable(requestPage));
    }

    @Override
    @Transactional
    public void deleteById(Long id) throws CmsCategoryException {
        CmsCategoryPO categoryPO = getEntityWithNullCheckForUpdate(id, categoryDAO);
        categoryPO.setDeletedTime(System.currentTimeMillis());
    }

    @Override
    protected Supplier<? extends RuntimeException> getExceptionSupplier(String message,
                                                                        Throwable cause) {
        return () -> new CmsCategoryException(message, cause);
    }

    @Autowired
    public void setCategoryDAO(CmsCategoryDAO categoryDAO) {
        this.categoryDAO = categoryDAO;
    }

    @Override
    public List<CmsCategory> findTopTree(Long id) {
        List<CmsCategoryPO> allPOList = categoryDAO.findAllByOrderByParentIdDescSortDescIdAsc();
        List<CmsCategory> categoryList = convertStreamQBeanToList(allPOList.stream());
        return CmsCategory.toTree(categoryList, id).getChildren();
    }

    @Override
    public List<CmsCategory> listByParent(Long parentId) {
        return convertStreamQBeanToList(categoryDAO.findAllByParentId(parentId).stream());
    }

    @Override
    public List<CmsCategory> listAllByParent(Long parentId, List<CmsCategory> all) {
        List<CmsCategory> childrens = listByParent(parentId);
        if (childrens.size() == 0) {
            return all;
        }
        all.addAll(childrens);
        for (CmsCategory category : childrens) {
            listAllByParent(category.getParentId(), all);
        }
        return all;
    }

    @Override
    public List<CmsCategory> findTopTree() {
        List<CmsCategoryPO> allPOList = categoryDAO.findAllByOrderByParentIdDescSortDescIdAsc();
        List<CmsCategory> categoryList = convertStreamQBeanToList(allPOList.stream());
        return CmsCategory.toTree(categoryList, 0L).getChildren();
    }

    @Override
    public CmsCategory getCategoryByCode(String code) {
        List<CmsCategoryPO> categoryPOList = categoryDAO.findAllByCode(code);
        if (categoryPOList.size() > 0) {
            return convertQBean(categoryPOList.get(0));
        }
        return null;
    }
}
